import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import '../models/models.dart';

/// Hive数据库服务类
/// 负责Hive数据库的初始化和本地缓存管理
class HiveService {
  static final HiveService _instance = HiveService._internal();
  factory HiveService() => _instance;
  HiveService._internal();

  // Box名称常量
  static const String _musicBoxName = 'music_box';
  static const String _userSettingsBoxName = 'user_settings_box';
  static const String _themeConfigBoxName = 'theme_config_box';
  static const String _cacheBoxName = 'cache_box';

  // Box实例
  Box<Music>? _musicBox;
  Box<UserSettings>? _userSettingsBox;
  Box<ThemeConfig>? _themeConfigBox;
  Box? _cacheBox;

  bool _isInitialized = false;

  /// 初始化Hive数据库
  Future<void> init() async {
    if (_isInitialized) return;

    // 初始化Hive
    await Hive.initFlutter();

    // 注册适配器
    _registerAdapters();

    // 打开所有Box
    await _openBoxes();

    // 初始化默认数据
    await _initializeDefaultData();

    _isInitialized = true;
  }

  /// 注册Hive适配器
  void _registerAdapters() {
    if (!Hive.isAdapterRegistered(0)) {
      Hive.registerAdapter(MusicAdapter());
    }
    if (!Hive.isAdapterRegistered(1)) {
      Hive.registerAdapter(UserSettingsAdapter());
    }
    if (!Hive.isAdapterRegistered(2)) {
      Hive.registerAdapter(ThemeConfigAdapter());
    }
    if (!Hive.isAdapterRegistered(3)) {
      Hive.registerAdapter(PlayModeAdapter());
    }
    if (!Hive.isAdapterRegistered(4)) {
      Hive.registerAdapter(ThemeModeAdapter());
    }
    if (!Hive.isAdapterRegistered(5)) {
      Hive.registerAdapter(AudioQualityAdapter());
    }
  }

  /// 打开所有Box
  Future<void> _openBoxes() async {
    _musicBox = await Hive.openBox<Music>(_musicBoxName);
    _userSettingsBox = await Hive.openBox<UserSettings>(_userSettingsBoxName);
    _themeConfigBox = await Hive.openBox<ThemeConfig>(_themeConfigBoxName);
    _cacheBox = await Hive.openBox(_cacheBoxName);
  }

  /// 初始化默认数据
  Future<void> _initializeDefaultData() async {
    // 初始化默认用户设置
    if (_userSettingsBox!.isEmpty) {
      final defaultSettings = UserSettings.defaultSettings();
      await _userSettingsBox!.put('default', defaultSettings);
    }

    // 初始化默认主题配置
    if (_themeConfigBox!.isEmpty) {
      final techDark = ThemeConfig.techDark();
      final techLight = ThemeConfig.techLight();
      await _themeConfigBox!.put(techDark.id, techDark);
      await _themeConfigBox!.put(techLight.id, techLight);
    }
  }

  /// 获取音乐Box
  Box<Music> get musicBox {
    if (_musicBox == null || !_musicBox!.isOpen) {
      throw Exception('Music box is not initialized');
    }
    return _musicBox!;
  }

  /// 获取用户设置Box
  Box<UserSettings> get userSettingsBox {
    if (_userSettingsBox == null || !_userSettingsBox!.isOpen) {
      throw Exception('User settings box is not initialized');
    }
    return _userSettingsBox!;
  }

  /// 获取主题配置Box
  Box<ThemeConfig> get themeConfigBox {
    if (_themeConfigBox == null || !_themeConfigBox!.isOpen) {
      throw Exception('Theme config box is not initialized');
    }
    return _themeConfigBox!;
  }

  /// 获取缓存Box
  Box get cacheBox {
    if (_cacheBox == null || !_cacheBox!.isOpen) {
      throw Exception('Cache box is not initialized');
    }
    return _cacheBox!;
  }

  /// 保存音乐到缓存
  Future<void> saveMusic(Music music) async {
    await musicBox.put(music.id, music);
  }

  /// 批量保存音乐
  Future<void> saveMusicList(List<Music> musicList) async {
    final Map<String, Music> musicMap = {
      for (Music music in musicList) music.id: music
    };
    await musicBox.putAll(musicMap);
  }

  /// 获取缓存的音乐
  Music? getCachedMusic(String id) {
    return musicBox.get(id);
  }

  /// 获取所有缓存的音乐
  List<Music> getAllCachedMusic() {
    return musicBox.values.toList();
  }

  /// 删除缓存的音乐
  Future<void> deleteCachedMusic(String id) async {
    await musicBox.delete(id);
  }

  /// 清空音乐缓存
  Future<void> clearMusicCache() async {
    await musicBox.clear();
  }

  /// 保存用户设置
  Future<void> saveUserSettings(UserSettings settings) async {
    await userSettingsBox.put('default', settings);
  }

  /// 获取用户设置
  UserSettings? getUserSettings() {
    return userSettingsBox.get('default');
  }

  /// 保存主题配置
  Future<void> saveThemeConfig(ThemeConfig themeConfig) async {
    await themeConfigBox.put(themeConfig.id, themeConfig);
  }

  /// 获取主题配置
  ThemeConfig? getThemeConfig(String id) {
    return themeConfigBox.get(id);
  }

  /// 获取所有主题配置
  List<ThemeConfig> getAllThemeConfigs() {
    return themeConfigBox.values.toList();
  }

  /// 删除主题配置
  Future<void> deleteThemeConfig(String id) async {
    await themeConfigBox.delete(id);
  }

  /// 保存缓存数据
  Future<void> saveCache(String key, dynamic value) async {
    await cacheBox.put(key, value);
  }

  /// 获取缓存数据
  T? getCache<T>(String key) {
    return cacheBox.get(key) as T?;
  }

  /// 删除缓存数据
  Future<void> deleteCache(String key) async {
    await cacheBox.delete(key);
  }

  /// 清空所有缓存
  Future<void> clearAllCache() async {
    await cacheBox.clear();
  }

  /// 获取缓存大小信息
  Map<String, int> getCacheInfo() {
    return {
      'music_count': musicBox.length,
      'user_settings_count': userSettingsBox.length,
      'theme_config_count': themeConfigBox.length,
      'cache_count': cacheBox.length,
    };
  }

  /// 压缩数据库
  Future<void> compact() async {
    await musicBox.compact();
    await userSettingsBox.compact();
    await themeConfigBox.compact();
    await cacheBox.compact();
  }

  /// 关闭所有Box
  Future<void> close() async {
    await _musicBox?.close();
    await _userSettingsBox?.close();
    await _themeConfigBox?.close();
    await _cacheBox?.close();
    _isInitialized = false;
  }

  /// 删除所有数据
  Future<void> deleteAllData() async {
    await musicBox.clear();
    await userSettingsBox.clear();
    await themeConfigBox.clear();
    await cacheBox.clear();
    
    // 重新初始化默认数据
    await _initializeDefaultData();
  }

  /// 检查是否已初始化
  bool get isInitialized => _isInitialized;

  /// 获取数据库路径
  Future<String> getDatabasePath() async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path;
  }
}

/// Music适配器（需要通过build_runner生成）
class MusicAdapter extends TypeAdapter<Music> {
  @override
  final int typeId = 0;

  @override
  Music read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return Music(
      id: fields[0] as String,
      title: fields[1] as String,
      artist: fields[2] as String,
      album: fields[3] as String?,
      filePath: fields[4] as String,
      duration: fields[5] as int,
      fileSize: fields[6] as int,
      coverArt: fields[7] as String?,
      genre: fields[8] as String?,
      year: fields[9] as int?,
      bitRate: fields[10] as int?,
      sampleRate: fields[11] as int?,
      isFavorite: fields[12] as bool,
      playCount: fields[13] as int,
      createdAt: fields[14] as DateTime,
      updatedAt: fields[15] as DateTime,
    );
  }

  @override
  void write(BinaryWriter writer, Music obj) {
    writer
      ..writeByte(16)
      ..writeByte(0)
      ..write(obj.id)
      ..writeByte(1)
      ..write(obj.title)
      ..writeByte(2)
      ..write(obj.artist)
      ..writeByte(3)
      ..write(obj.album)
      ..writeByte(4)
      ..write(obj.filePath)
      ..writeByte(5)
      ..write(obj.duration)
      ..writeByte(6)
      ..write(obj.fileSize)
      ..writeByte(7)
      ..write(obj.coverArt)
      ..writeByte(8)
      ..write(obj.genre)
      ..writeByte(9)
      ..write(obj.year)
      ..writeByte(10)
      ..write(obj.bitRate)
      ..writeByte(11)
      ..write(obj.sampleRate)
      ..writeByte(12)
      ..write(obj.isFavorite)
      ..writeByte(13)
      ..write(obj.playCount)
      ..writeByte(14)
      ..write(obj.createdAt)
      ..writeByte(15)
      ..write(obj.updatedAt);
  }

  @override
  int get hashCode => typeId.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is MusicAdapter &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}

/// UserSettings适配器
class UserSettingsAdapter extends TypeAdapter<UserSettings> {
  @override
  final int typeId = 1;

  @override
  UserSettings read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return UserSettings(
      id: fields[0] as String,
      themeMode: fields[1] as ThemeMode,
      volume: fields[2] as double,
      playMode: fields[3] as PlayMode,
      audioQuality: fields[4] as AudioQuality,
      shuffleEnabled: fields[5] as bool,
      equalizerPreset: fields[6] as String? ?? 'default',
      crossfadeEnabled: fields[7] as bool,
      crossfadeDuration: fields[8] as int,
      lyricsEnabled: fields[9] as bool,
      sleepTimerEnabled: fields[10] as bool,
      sleepTimerDuration: fields[11] as int,
      hapticFeedbackEnabled: fields[12] as bool,
      lockScreenControlEnabled: fields[13] as bool,
      updatedAt: fields[14] as DateTime,
    );
  }

  @override
  void write(BinaryWriter writer, UserSettings obj) {
    writer
      ..writeByte(15)
      ..writeByte(0)
      ..write(obj.id)
      ..writeByte(1)
      ..write(obj.themeMode)
      ..writeByte(2)
      ..write(obj.volume)
      ..writeByte(3)
      ..write(obj.playMode)
      ..writeByte(4)
      ..write(obj.audioQuality)
      ..writeByte(5)
      ..write(obj.shuffleEnabled)
      ..writeByte(6)
      ..write(obj.equalizerPreset)
      ..writeByte(7)
      ..write(obj.crossfadeEnabled)
      ..writeByte(8)
      ..write(obj.crossfadeDuration)
      ..writeByte(9)
      ..write(obj.lyricsEnabled)
      ..writeByte(10)
      ..write(obj.sleepTimerEnabled)
      ..writeByte(11)
      ..write(obj.sleepTimerDuration)
      ..writeByte(12)
      ..write(obj.hapticFeedbackEnabled)
      ..writeByte(13)
      ..write(obj.lockScreenControlEnabled)
      ..writeByte(14)
      ..write(obj.updatedAt);
  }

  @override
  int get hashCode => typeId.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is UserSettingsAdapter &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}

/// ThemeConfig适配器
class ThemeConfigAdapter extends TypeAdapter<ThemeConfig> {
  @override
  final int typeId = 2;

  @override
  ThemeConfig read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return ThemeConfig(
      id: fields[0] as String,
      themeName: fields[1] as String,
      primaryColor: fields[2] as String,
      accentColor: fields[3] as String,
      backgroundColor: fields[4] as String,
      surfaceColor: fields[5] as String,
      isDark: fields[6] as bool,
      createdAt: fields[7] as DateTime,
    );
  }

  @override
  void write(BinaryWriter writer, ThemeConfig obj) {
    writer
      ..writeByte(8)
      ..writeByte(0)
      ..write(obj.id)
      ..writeByte(1)
      ..write(obj.themeName)
      ..writeByte(2)
      ..write(obj.primaryColor)
      ..writeByte(3)
      ..write(obj.accentColor)
      ..writeByte(4)
      ..write(obj.backgroundColor)
      ..writeByte(5)
      ..write(obj.surfaceColor)
      ..writeByte(6)
      ..write(obj.isDark)
      ..writeByte(7)
      ..write(obj.createdAt);
  }

  @override
  int get hashCode => typeId.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is ThemeConfigAdapter &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}

/// PlayMode枚举适配器
class PlayModeAdapter extends TypeAdapter<PlayMode> {
  @override
  final int typeId = 3;

  @override
  PlayMode read(BinaryReader reader) {
    switch (reader.readByte()) {
      case 0:
        return PlayMode.sequence;
      case 1:
        return PlayMode.shuffle;
      case 2:
        return PlayMode.repeatAll;
      case 3:
        return PlayMode.repeatOne;
      default:
        return PlayMode.sequence;
    }
  }

  @override
  void write(BinaryWriter writer, PlayMode obj) {
    switch (obj) {
      case PlayMode.sequence:
        writer.writeByte(0);
        break;
      case PlayMode.shuffle:
        writer.writeByte(1);
        break;
      case PlayMode.repeatAll:
        writer.writeByte(2);
        break;
      case PlayMode.repeatOne:
        writer.writeByte(3);
        break;
    }
  }

  @override
  int get hashCode => typeId.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is PlayModeAdapter &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}

/// ThemeMode枚举适配器
class ThemeModeAdapter extends TypeAdapter<ThemeMode> {
  @override
  final int typeId = 4;

  @override
  ThemeMode read(BinaryReader reader) {
    switch (reader.readByte()) {
      case 0:
        return ThemeMode.system;
      case 1:
        return ThemeMode.light;
      case 2:
        return ThemeMode.dark;
      default:
        return ThemeMode.system;
    }
  }

  @override
  void write(BinaryWriter writer, ThemeMode obj) {
    switch (obj) {
      case ThemeMode.system:
        writer.writeByte(0);
        break;
      case ThemeMode.light:
        writer.writeByte(1);
        break;
      case ThemeMode.dark:
        writer.writeByte(2);
        break;
    }
  }

  @override
  int get hashCode => typeId.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is ThemeModeAdapter &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}

/// AudioQuality枚举适配器
class AudioQualityAdapter extends TypeAdapter<AudioQuality> {
  @override
  final int typeId = 5;

  @override
  AudioQuality read(BinaryReader reader) {
    switch (reader.readByte()) {
      case 0:
        return AudioQuality.standard;
      case 1:
        return AudioQuality.high;
      case 2:
        return AudioQuality.lossless;
      default:
        return AudioQuality.high;
    }
  }

  @override
  void write(BinaryWriter writer, AudioQuality obj) {
    switch (obj) {
      case AudioQuality.standard:
        writer.writeByte(0);
        break;
      case AudioQuality.high:
        writer.writeByte(1);
        break;
      case AudioQuality.lossless:
        writer.writeByte(2);
        break;
    }
  }

  @override
  int get hashCode => typeId.hashCode;

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is AudioQualityAdapter &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}